// 引入 Speex 的头文件（包含编解码 API）
#include <speex/speex.h>
// 提供 malloc / free 内存分配函数
#include <stdlib.h>

// ------------------- 定义编码器结构 -------------------
typedef struct {
    void *state;      // Speex 编码器的内部状态（由 Speex 管理）
    SpeexBits bits;   // SpeexBits 是 Speex 提供的比特流缓存工具
    int frame_size;   // 一帧 PCM 数据的采样点数量（比如 16kHz 下通常是 320）
} SpeexEncoder;

// ------------------- 定义解码器结构 -------------------
typedef struct {
    void *state;      // Speex 解码器的内部状态
    SpeexBits bits;   // 用来存储压缩数据（Speex 帧）并提供给解码器
    int frame_size;   // 一帧 PCM 数据的采样点数量
} SpeexDecoder;

// =====================================================
// ================== Speex 编码部分 ===================
// =====================================================

// 初始化 Speex 编码器，返回一个 SpeexEncoder 结构体指针
// 参数：
//   quality - 压缩质量（0 ~ 10，数值越大质量越好、比特率越高）
//   sample_rate - 采样率（此处未直接使用，但可用于以后扩展）
SpeexEncoder* speex_encoder_init_wrapper(int quality, int sample_rate) {
    // 分配一个 SpeexEncoder 结构体
    SpeexEncoder* encoder = (SpeexEncoder*)malloc(sizeof(SpeexEncoder));
    // 初始化 SpeexBits，用来缓存编码后的比特流
    speex_bits_init(&encoder->bits);
    // 初始化 Speex 编码器，使用“宽带模式”（wb = wideband, 16kHz）
    encoder->state = speex_encoder_init(&speex_wb_mode); // 宽带模式
    // 设置编码质量
    speex_encoder_ctl(encoder->state, SPEEX_SET_QUALITY, &quality);
    // 获取一帧的 PCM 采样点数量（frame_size），保存到结构体中
    speex_encoder_ctl(encoder->state, SPEEX_GET_FRAME_SIZE, &encoder->frame_size);
    return encoder;
}

// 编码一帧 PCM 数据
// 参数：
//   encoder - 已经初始化的编码器
//   pcm - 输入的 PCM 数据（short 数组，长度必须等于 frame_size）
//   output - 输出缓存，用来存放编码后的字节数据
//   max_len - output 缓存的最大长度
// 返回值：
//   实际写入 output 的字节数（即压缩帧的大小）
int speex_encode_frame(SpeexEncoder* encoder, short* pcm, char* output, int max_len) {
    // 清空比特流缓存
    speex_bits_reset(&encoder->bits);
    // 编码一帧 PCM 数据，结果写入 encoder->bits
    speex_encode_int(encoder->state, pcm, &encoder->bits);
    // 从 encoder->bits 中写出压缩数据到 output，返回字节数
    int nbBytes = speex_bits_write(&encoder->bits, output, max_len);
    return nbBytes;
}

// 获取编码器的一帧 PCM 的采样点数量
int speex_get_frame_size(SpeexEncoder* encoder) {
    return encoder->frame_size;
}

// 销毁编码器，释放内存
void speex_encoder_destroy_wrapper(SpeexEncoder* encoder) {
    if (encoder) {
        // 释放 SpeexBits 内部资源
        speex_bits_destroy(&encoder->bits);
        // 销毁 Speex 编码器状态
        speex_encoder_destroy(encoder->state);
        // 释放分配的结构体内存
        free(encoder);
    }
}

// =====================================================
// ================== Speex 解码部分 ===================
// =====================================================

// 初始化 Speex 解码器
// 使用宽带模式（16kHz）
SpeexDecoder* speex_decoder_init_wrapper() {
    // 分配解码器结构体
    SpeexDecoder* decoder = (SpeexDecoder*)malloc(sizeof(SpeexDecoder));
    // 初始化 SpeexBits，用来接收压缩数据
    speex_bits_init(&decoder->bits);
    // 初始化解码器（宽带模式，16kHz）
    decoder->state = speex_decoder_init(&speex_wb_mode);
    // 获取解码器的 frame_size（PCM 一帧采样点数量）
    speex_decoder_ctl(decoder->state, SPEEX_GET_FRAME_SIZE, &decoder->frame_size);
    return decoder;
}

// 解码一帧 Speex 压缩数据
// 参数：
//   decoder - 已经初始化的解码器
//   input - 输入的 Speex 压缩数据（即一帧）
//   len - 输入数据的字节数
//   output - 输出的 PCM 数据（short 数组，长度至少为 frame_size）
// 返回值：
//   0 表示成功，负数表示出错
int speex_decode_frame_wrapper(SpeexDecoder* decoder, char* input, int len, short* output) {
    // 把 input 压缩数据读入 decoder->bits
    speex_bits_read_from(&decoder->bits, input, len);
    // 解码一帧数据，结果写到 output（short PCM 数组）
    return speex_decode_int(decoder->state, &decoder->bits, output);
}

// 获取解码器的一帧 PCM 采样点数
int speex_get_frame_size_decoder(SpeexDecoder* decoder) {
    return decoder->frame_size;
}

// 销毁解码器
void speex_decoder_destroy_wrapper(SpeexDecoder* decoder) {
    if (decoder) {
        // 释放 SpeexBits
        speex_bits_destroy(&decoder->bits);
        // 销毁解码器状态
        speex_decoder_destroy(decoder->state);
        // 释放内存
        free(decoder);
    }
}